/**
 * 校验规则库
 * 用法：
 * 1、{ validator: formValidate('fullName', '校验不通过提示，传空字符串会使用默认提示', (errMsg, index) => { }), trigger: 'blur' } // 普通预设正则校验
 * 2、{ validator: formValidate(/^(?!.*\\)(?!.*\^)/, '输入的值不能含有反斜杠和"^"', (errMsg, index) => { }), trigger: 'blur' } // 自定义正则校验
 * 3、{ validator: formValidate({ type: 'decimal', params: [10, 6, "校验不通过提示，传空字符串会使用默认提示", (errMsg, index) => { }] }), trigger: 'blur' } // 携带参数的预设校验
**/
const regularList = {
  'iphone': {
    rule: /^1[3456789]\d{9}$/,
    msg: '请输入正确的手机号'
  },
  'password': {
    rule: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$/,
    msg: '请输入6-16位字符的密码（数字和字母组成）'
  },
  'idCard': {
    rule: /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X|x)$/,
    msg: '请输入正确的身份证号码'
  },
  'email': {
    rule: /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/,
    msg: '请输入正确的邮箱地址'
  },
  'plateNumber': {
    rule: /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/,
    msg: '请输入正确的车牌号'
  },
  /**数值校验
   * @param {number} a 数值总位数
   * @param {number} b 最长小数位数
   * @param {string} msg 错误提示
   * @param {number} callbackMethod 错误回调方法
   * 示例：{ validator: formValidate({ type: 'decimal', params: [10, 2, "", (errMsg, index) => { console.log(`第${index + 1}行：数量${errMsg}`) }] }), trigger: 'blur' },
   */
  decimal(a: number, b: number, msg?: string, callbackMethod?: any) {
    return (rule: ObjectAny, value: any, callback: (error?: Error) => void) => {
      const index = getIndex(rule)
      const reg = new RegExp(`^(0|[1-9](\\d{0,${a - b - 1}}))((\\.\\d{1,${b}})?)$`);
      msg = msg || `请输入正确的数值，整数不能超过${a - b}位，小数不能超过${b}位`
      if (!value || reg.test(value) || value === '0') { callback() }
      else {
        if (callbackMethod) { callbackMethod(msg, index) }
        callback(new Error(msg));
      }
    };
  },
  /**自定义逻辑校验
   * @param {number} calcMethod 数值总位数
   * @param {string} msg 错误提示
   * @param {number} callbackMethod 错误回调方法
   * 示例：{ validator: formValidate({ type: 'calc', params: [(rowIndex, value) => linesList[rowIndex].num_1 <= linesList[rowIndex].num_2, "不能超过对应数量_2", (errMsg, index) => { console.log(`第${index + 1}行：数量${errMsg}`) }), trigger: 'blur' }
   */
  calc(calcMethod: (index?: number, value?: any) => Boolean, msg?: any, callbackMethod?: any) {
    // 注意：数学式逻辑判断 请确保其字段类型正确
    return (rule: ObjectAny, value: any, callback: (error?: Error) => void) => {
      const index = getIndex(rule)
      msg = msg || `不符合calc校验规则`
      if (!value) { callback() }
      else {
        const flag = !calcMethod(index, value)
        if (flag) {
          if (callbackMethod) { callbackMethod(msg, index) }
          callback(new Error(msg));
        } else { callback() }
      }
    };
  },
  /**带回调方法的非空校验
   * @param {string} msg 错误提示
   * @param {number} callbackMethod 错误回调方法
   * 示例：{ validator: formValidate({ type: 'required', params: ['密码不能为空', (errMsg: string) => { console.log('校验失败回调', errMsg) }] }) }
   */
  required(msg?: any, callbackMethod?: any) {
    return (rule: ObjectAny, value: any, callback: (error?: Error) => void) => {
      const index = getIndex(rule)
      msg = msg || `不能为空`
      if (value === '' || value === null || value === undefined) {
        if (callbackMethod) { callbackMethod(msg, index) }
        callback(new Error(msg));
      } else {
        callback()
      }
    };
  },
}

/**formValidate参数 */
interface FormValidateOption {
  type: 'iphone' | 'password' | 'idCard' | 'email' | 'plateNumber' | 'decimal' | 'calc' | 'required'
  message?: string
  params?: any[]
  errCallBack?: (msg: string, index?: number) => void
}
const formValidate = ({ type, message, errCallBack, params = [] }: FormValidateOption) => {
  // 解析
  if (typeof regularList[type] === "function") return (regularList as any)[type](...params) // 校验类型指向funtion，调用预设的校验方法
  // else if (typeof reg === "string") reg = RegExp(reg) // 是字符串则转成正则表达式

  return (rule: any, value: any, callback: (error?: Error) => void) => {
    /**校验类型 | 正则表达式 | 正则字符串 */
    const reg = (type in regularList && 'rule' in regularList[type]) ? (regularList[type] as ObjectAny).rule : type


    /**校验行的索引 */
    const index = getIndex(rule)

    /**校验失败message */
    const msg = message || ((regularList[type] && (regularList[type] as ObjectAny).msg) ? (regularList[type] as ObjectAny).msg : '')

    // 校验
    if (value === '' || value === null || value === undefined) { callback() }
    else if (!(reg as RegExp).test(value)) {
      if (errCallBack) errCallBack(msg, index)
      callback(new Error(msg))
    } else { callback() }
  }
}

/**
 * 如果是表格式表单，获取校验行的索引
 * @param rule rule
 * @return {number} 校验行索引
*/
function getIndex(rule: ObjectAny): number | undefined {
  const temp = rule.field.match(/\d+/)
  return temp ? Number(temp[0]) : undefined
}

export default formValidate